#pragma once
#include "level.hpp"
#include <string>
#include <ctime>
#include "message.hpp"
#include <vector>
#include <cassert>
#include <sstream>
namespace bitlog{
    //抽象格式化子项基类
    class FormatItem{
        public:
        using ptr = std::shared_ptr<FormatItem>;
            virtual void format(std::ostream& out,const LogMsg& msg) = 0;
    };
    //派生类格式化子项子类
    class MsgFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<msg._payload;
         }
         };
    class LevelFormatItem:public FormatItem{
        public:
        void format(std::ostream& out,const LogMsg& msg)override{
            out<<LogLevel::toString(msg._level);
         }
    };
     class TimeFormatItem:public FormatItem{
        public:
        TimeFormatItem(const std::string &fmt = "%H:%M:%S"):_time_fmt(fmt){}
        void format(std::ostream& out,const LogMsg& msg)override{
            struct tm t;
            localtime_r((const time_t*)&msg._ctime,&t);
            char tmp[32] = {0};
            strftime(tmp,31,_time_fmt.c_str(),&t);
            out<<tmp;
         }
         private:
            std::string _time_fmt;
    };
    class FileFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<msg._file;
         }
         };
    class LineFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<msg._line;
         }
         };
     class ThreadFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<msg._tid;
         }
         };
    class LoggerFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<msg._logger;
         }
         };
    class TabFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<"\t";
         }
         };
    class NlineFormatItem:public FormatItem{
        public:
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<"\n";
         }
         };
    class OtherFormatItem:public FormatItem{
        public:
        OtherFormatItem(const std::string& str)
        :_str(str)
        {

        }
         void format(std::ostream& out,const LogMsg& msg)override{
            out<<_str;
        }
        private:
            std::string _str;
        };
        // %d 表示日期，包含子格式
        // %t 表示线程id
        // %c 表示日志器名称
        // %f 表示源码文件名
        // %l 表示源码行号
        // %p 表示日志级别
        // %T 表示制表符缩进
        // %m 表示主题消息
        // %n 表示换行
    class Formatter {
        public:
        using ptr = std::shared_ptr<Formatter>;
        Formatter(const std::string& pattern = "[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
        :_pattern(pattern){
            assert(parsePattern());
        }
        void format(std::ostream &out,const LogMsg& msg){
            for(auto &e: _items){
                e->format(out,msg);
            }
        }
        std::string format(const LogMsg& msg){
            std::stringstream ss;
            format(ss,msg);
            return ss.str();
        }
        private:
        bool parsePattern(){//对格式化规则字符串进行解析
        std::vector<std::pair<std::string,std::string>> fmt_order;
        size_t pos = 0;std::string key,val;
        while(pos<_pattern.size()){
        //判断是不是%--判断是否是%
        
        if(_pattern[pos] != '%'){
            val.push_back(_pattern[pos++]);continue;
        }
        if(pos + 1 <_pattern.size()&& _pattern[pos+1] == '%'){
            val.push_back(_pattern['%']);pos+=2;continue;
        }
        if(val.empty()==false)
        {
        fmt_order.push_back(std::make_pair("",val));
        val.clear();   
        }
        pos+=1;
        if(pos  ==_pattern.size())
        {
            std::cout<<"%之后，没有格式化字符"<<std::endl;
            return false;
        }
        key = _pattern[pos];
        //这时候pos指向pos格式化字符后的位置
        pos+=1;
        if(pos < _pattern.size()&& _pattern[pos] == '{'){
            pos+=1;//pos处于子规则起始位置
            while(pos < _pattern.size()&&_pattern[pos]!='}'){
                val.push_back(_pattern[pos]);
                pos+=1;
            }
            if(pos==_pattern.size()){
                std::cout<<"子规则{}匹配出错\n"<<std::endl;
               return false; 
            }//判断子规则格式是否正确,到了末尾也没有遇到}，代表格式错误
            pos+=1;
        }
        fmt_order.push_back(std::make_pair(key,val));
        key.clear();
        val.clear();
        }
        for(auto &it: fmt_order){
            _items.push_back(createItem(it.first,it.second));
        }
        
            return true;
        }
        private:
            FormatItem::ptr createItem(const std::string& key,const std::string &val){
                if(key == "d")return std::make_shared<TimeFormatItem>(val);
                if(key == "t")return std::make_shared<ThreadFormatItem>();
                if(key == "c")return std::make_shared<LoggerFormatItem>();
                if(key == "f")return std::make_shared<FileFormatItem>();
                if(key == "l")return std::make_shared<LineFormatItem>();
                if(key == "p")return std::make_shared<LevelFormatItem>();
                if(key == "T")return std::make_shared<TabFormatItem>();
                if(key == "m")return std::make_shared<MsgFormatItem>();
                if(key == "n")return std::make_shared<NlineFormatItem>();
                if(key.empty())return std::make_shared<OtherFormatItem>(val);
                std::cout<<"没有格式化字符%"<<key<<std::endl;
                abort();
                return FormatItem::ptr();
            }
        private:
            std::string _pattern;//格式化规则字符串
            std::vector<FormatItem::ptr> _items;
    };
}